<?php

namespace app\api\service;

use addons\qcloudsms\library\SmsMobileStatusPuller;
use app\api\controller\Validate;
use app\api\model\AdminModel;
use app\api\model\AgentCompanyModel;
use app\api\model\AgentModel;
use app\api\model\BackListAreaModel;
use app\api\model\BackListCompanyModel;
use app\api\model\BackListKeywordsModel;
use app\api\model\CompanyModel;
use app\api\model\OrderApplicationModel;
use app\api\model\OrderCorrectRecordModel;
use app\api\model\OrderEmployeeRecordModel;
use app\api\model\OrderInsuredModel;
use app\api\model\OrderInvoiceModel;
use app\api\model\OrderModel;
use app\api\model\ProductInfoModel;
use app\api\model\ProductModel;
use app\api\model\ProductRuleModel;
use app\api\model\WorkCategoryModel;
use app\api\model\WorkTypeModel;
use app\common\model\Area;
use bgb\office\excel\Excel;
use bgb\office\word\Word;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\IOFactoryTest;
use PhpOffice\PhpWord\TemplateProcessor;
use think\Config;
use think\Db;
use think\Exception;
use think\Request;

class OrderService extends Api
{
    protected static $instance;
    protected $uStatus = [
        1 => '待支付',
        2 => '待审核',
        3 => '待生效',
        4 => '驳回',
        5 => '待生效',
        6 => '保障中',
        7 => '已过期',
        8 => '已取消',
        9 => '申请退款',
        10 => '已退款',
        11 => '待传资料',
        12 => '',
        13 => '保前审核',
        15 => '待传资料',
    ];
    protected $status = [
        1 => '待支付',
        2 => '待审核',
        3 => '审核通过',
        4 => '驳回',
        5 => '审核通过',
        6 => '审核通过',
        7 => '审核通过',
        8 => '已取消',
        9 => '申请退款',
        10 => '已退款',
        11 => '待传资料',
        12 => '',
        13 => '保前审核',
        15 => '审核通过',
    ];
    protected $ratio = [
        1 => 10,
        2 => 20,
        3 => 30,
        4 => 40,
        5 => 50,
        6 => 60,
        7 => 70,
        8 => 80,
        9 => 85,
        10 => 90,
        11 => 95,
        12 => 100,
    ];

    public function __construct(Request $request = null)
    {
        parent::__construct($request);
    }

    public static function getInstance()
    {
        if (is_null(self::$instance))
        {
            self::$instance = new static();
        }
        return self::$instance;
    }

    /**
     * 投保
     */
    public function createOrder($params)
    {
        $Validate = new \think\Validate([
            'applicationName' => 'require',
            'applicationCode' => 'require',
            'applicationProvince' => 'require',
            'applicationCity' => 'require',
            'applicationArea' => 'require',
            'applicationAddress' => 'require',
            'applicationPhone' => 'require',
            'applicationCodeImg' => 'require',
            'applicationLegalPerson' => 'require',
            'insuredName' => 'require',
            'insuredCode' => 'require',
            'insuredProvince' => 'require',
            'insuredCity' => 'require',
            'insuredArea' => 'require',
            'insuredAddress' => 'require',
            'insuredPhone' => 'require',
            'insuredCodeImg' => 'require',
            'insuredLegalPerson' => 'require',
            'product_id' => 'require',
            'planId' => 'require',
//            'disabRatio' => 'require',
            'isAllDays' => 'require',
            'guaranteePeriod' => 'require',
            'workType' => 'require',
            'workId' => 'require',
            'personList' => 'require',
            'sTime' => 'require',
            'isHaveBill' => 'require',
        ], [
            'product_id' => '产品标识无效',
            'planId' => '方案标识无效',
            'disabRatio' => '伤残比例无效',
            'isAllDays' => '是否扩展24小时必传',
            'guaranteePeriod' => '保障期限无效',
            'workType' => '工种类别必传',
            'workId' => '工种必传',
            'personList' => '人员列表必传',
            'applicationName' => '投保名称必填',
            'applicationCode' => '投保证件号码必填',
            'applicationProvince' => '投保地区省份必填',
            'applicationCity' => '投保地区市区必填',
            'applicationArea' => '投保地区区域必填',
            'applicationAddress' => '投保详细地址必填',
            'applicationPhone' => '投保联系方式必填',
            'applicationCodeImg' => '投保证件图片必填',
            'applicationLegalPerson' => '投保负责人、法人必填',
            'insuredName' => '被保名称必填',
            'insuredCode' => '被保证件号码必填',
            'insuredProvince' => '被保地区省份必填',
            'insuredCity' => '被保地区市区必填',
            'insuredArea' => '被保地区区域必填',
            'insuredAddress' => '被保详细地址必填',
            'insuredPhone' => '被保联系方式必填',
            'insuredCodeImg' => '被保证件图片必填',
            'insuredLegalPerson' => '被保负责人、法人必填',
            'sTime' => '起保时间无效',
            'isHaveBill' => '是否开票必填'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $Validate = new \think\Validate([
            'idCardType' => 'require',
            'name' => 'require',
            'idCardNum' => 'require'
        ], [
            'idCardType' => '证件类型无效',
            'name' => '人员姓名不能为空',
            'idCardNum' => '人员证件号不能为空'
        ]);
        if (!$Validate->check($params['personList'][0]))
        {
            $this->error($Validate->getError());
        }

        if ($params['isHaveBill'])
        {
            $params['invoiceType'] = $this->request->param('invoiceType', 1);
            if ($params['invoiceType'] == 2)
            {
                $checkData = [
                    'taxpayer_name' => 'require',//纳税人名称',
                    'taxpayer_id' => 'require',//纳税人识别号',
                    'taxpayer_addr' => 'require',//税务登记地址',
                    'taxpayer_tel' => 'require',//税务登记联系电话',
                    'taxpayer_bank' => 'require',//税务开户银行名称',
                    'taxpayer_bankno' => 'require',//税务开户银行名称',
                    'ext_info' => 'require',//'一般纳税人证明等其他文件信息',
//                    'invoice_phone' => 'require',//'收件人手机号',
//                    'address' => 'require',//'收件人地址',
//                    'new_contact_name' => 'require',//'收件人',
                ];
                $checkMsg = [
                    'taxpayer_name' => '纳税人名称必传',//纳税人名称',
                    'taxpayer_id' => '纳税人识别号必传',//纳税人识别号',
                    'taxpayer_addr' => '税务登记地址必传',//税务登记地址',
                    'taxpayer_tel' => '税务登记联系电话必传',//税务登记联系电话',
                    'taxpayer_bank' => '税务开户银行名称必传',//税务开户银行名称',
                    'taxpayer_bankno' => '税务开户银行名称必传',//税务开户银行名称',
                    'ext_info' => '一般纳税人证明等其他文件信息必传',//'一般纳税人证明等其他文件信息',
//                    'invoice_phone' => '收件人手机号必传',//'收件人手机号',
//                    'address' => '收件人地址必传',//'收件人地址',
//                    'new_contact_name' => '收件人必传',//'收件人',
                ];
            }else{
                $checkData = [
                    'taxpayer_name' => 'require',//纳税人名称',
                    'taxpayer_id' => 'require',//纳税人识别号',
//                    'ext_info' => 'require',//'一般纳税人证明等其他文件信息',
                ];
                $checkMsg = [
                    'taxpayer_name' => '纳税人名称必传',//纳税人名称',
                    'taxpayer_id' => '纳税人识别号必传',//纳税人识别号',
//                    'ext_info' => '一般纳税人证明等其他文件信息必传',//'一般纳税人证明等其他文件信息',
                ];
            }
            $Validate = new \think\Validate($checkData, $checkMsg);
            if (!$Validate->check($params))
            {
                $this->error($Validate->getError());
            }
        }

        Db::startTrans();
        try{
            //拒保
            self::checkInsuredStatus([
                'companyName' => $params['applicationName'],
                'companyCode' => $params['applicationCode'],
                'province' => $params['applicationProvince'],
                'city' => $params['applicationCity'],
                'area' => $params['applicationArea'],
                'productId' => $params['product_id'],
            ]);

            $numId = $this->getNumId();
            $plan = ClientProductService::getInstance()->getProductPlan($params);
            $baseMoney = ClientProductService::getInstance()->getProductPlanMoney($params);
            $timeRule = ClientProductService::getInstance()->getProductTimeRule([
                'product_id' => $params['product_id'],
                'identification' => 1
            ]);
            $sTime = $timeRule['startTime'] > $params['sTime'] ? $timeRule['startTime'] : $params['sTime'];
            $endTime = $this->getNmonth($params['sTime'], $params['guaranteePeriod']);

            $workType = WorkTypeModel::getInstance()->find($params['workId'][3], 'title, cate_id');
            $workCate = WorkCategoryModel::getInstance()->find($workType['cate_id'], 'title');

            self::checkProductRule($params['personList'], $plan);

            $planList = array_column($plan['plan'], 'id');
            $planKey = array_search($params['planId'], $planList);
            $insurePlan = $plan['plan'][$planKey];
            $insurePlan['disabRatio'] = $params['disabRatio'];
            $insurePlan['isAllDays'] = $params['isAllDays'];

            $status = self::getOrderStatus($params['product_id'], $params['workId'][3]);

            $orderData = [
                'admin_id' => $this->uid,
                'num_id' => $numId,
                'policy_money' => $baseMoney['policyMoney'] * count($params['personList']),
                'buy_count' => count($params['personList']),
                'guarantee' => (strtotime($endTime) - strtotime($sTime)) / 24 / 3600 + 1,
                'status' => $status,//'订单状态：1 待支付  2 待审核  3 审核成功  4 审核失败  5 待生效  6 保障中  7 已过期  8 已取消  9 申请退款  10 已退款  11 待上传资料   12 空缺  13 保前审核',
                'product_id' => $params['product_id'],
                'product_plan' => json_encode(array_merge($insurePlan, $params['workType'], $params['workId'])),//json DEFAULT NULL COMMENT '投保方案',
                's_time' => $sTime,//datetime DEFAULT NULL COMMENT '生效日期',
                'e_time' => $endTime,//datetime DEFAULT NULL COMMENT '终止日期',
                'work_cate_title' => $workCate['title'],//varchar(128) DEFAULT NULL COMMENT '工种类别',
                'work_type_title' => $workType['title'],//varchar(128) DEFAULT NULL COMMENT '工种',
                'is_have_bill' => $params['isHaveBill'],
                'c_time' => datetime(time(), 'Y-m-d H:i:s')
            ];
            $personIdCard = array_column($params['personList'], 'idCardNum');
            $diffPerson = array_diff_assoc($personIdCard, array_unique($personIdCard));
            if (!empty($diffPerson))
            {
                $this->error('证件号为：'.implode(',', $diffPerson).'信息重复');
            }

            $applicationData = [
                'admin_id' => $this->uid,
                'num_id' => $numId,
                'name' => $params['applicationName'],
                'code' => str_replace(' ', '', $params['applicationCode']),
                'province' => $params['applicationProvince'],
                'city' => $params['applicationCity'],
                'area' => $params['applicationArea'],
                'address' => $params['applicationAddress'],
                'phone' => $params['applicationPhone'],
                'code_img' => $params['applicationCodeImg'],
                'legal_person' => $params['applicationLegalPerson'],
                'c_time' => datetime(time(), 'Y-m-d H:i:s'),
                'business_site' => $params['businessSite']
            ];
            $insureData = [
                'admin_id' => $this->uid,
                'num_id' => $numId,
                'name' => $params['insuredName'],
                'code' => str_replace(' ', '', $params['insuredCode']),
                'province' => $params['insuredProvince'],
                'city' => $params['insuredCity'],
                'area' => $params['insuredArea'],
                'address' => $params['insuredAddress'],
                'phone' => $params['insuredPhone'],
                'code_img' => $params['insuredCodeImg'],
                'legal_person' => $params['insuredLegalPerson'],
                'c_time' => datetime(time(), 'Y-m-d H:i:s'),
                'business_site' => $params['insuredBusinessSite'],
            ];
            $employeeRecord = [];
            foreach ($params['personList'] as $k => $v)
            {
                $employeeRecord[] = [
                    'num_id' => $numId,
                    'name' => $v['name'],
                    'code' => str_replace(' ', '', $v['idCardNum']),
                    'type' => 0,
                    'money' => $baseMoney['policyMoney'],
                    's_time' => $sTime,
                    'e_time' => $endTime,
                    'work_cate_title' => $workCate['title'],
                    'work_type_title' => $workType['title'],
                    'c_time' => datetime(time(), 'Y-m-d H:i:s')
                ];
            }
            Db::name('order')->insert($orderData);
            Db::name('order_application')->insert($applicationData);
            Db::name('order_insured')->insert($insureData);
            Db::name('order_employee_record')->insertAll($employeeRecord);

            if ($params['isHaveBill'])
            {
                $saveData = [
                    'num_id' => $numId,
                    'taxpayer_name' => isset($params['taxpayer_name']) ? $params['taxpayer_name'] : $params['applicationName'],
                    'type' => isset($params['invoiceType']) ? $params['invoiceType'] : 1,
                    'taxpayer_id' => isset($params['taxpayer_id']) ? $params['taxpayer_id'] : $params['applicationCode'],
                    'taxpayer_addr' => isset($params['taxpayer_addr']) ? $params['taxpayer_addr'] : $params['applicationAddress'],
                    'taxpayer_tel' => isset($params['taxpayer_tel']) ? $params['taxpayer_tel'] : $params['applicationPhone'],
                    'taxpayer_bank' => isset($params['taxpayer_bank']) ? $params['taxpayer_bank'] : '',
                    'taxpayer_bankno' => isset($params['taxpayer_bankno']) ? $params['taxpayer_bankno'] : '',
                    'ext_info' => isset($params['ext_info']) ? json_encode($params['ext_info']) : json_encode($params['applicationCodeImg']),
                    'invoice_phone' => isset($params['invoice_phone']) ? $params['invoice_phone'] : $params['applicationPhone'],
                    'address' => isset($params['address']) ? $params['address'] : $params['applicationAddress'],
                    'new_contact_name' => isset($params['new_contact_name']) ? $params['new_contact_name'] : $params['applicationLegalPerson'],
//                    'c_time' => datetime(time(), 'Y-m-d H:i:s')
                ];
                Db::name('order_invoice')->insert($saveData);
            }

            //还没有生成投保资料
            $params['numId'] = $numId;
            $fileUrl = self::createInsuredFile($params);
            if (!empty($fileUrl))
            {
                $fileUrl = json_encode($fileUrl);
                Db::name('order')->where([
                    'num_id' => ['eq', $params['numId']]
                ])->update([
                    'insure_file' => $fileUrl
                ]);
            }

            LogService::getInstance()->writeSysLog([
                'operation' => '/api/order/createOrder',
                'title' => '投保：流水号'.$numId,
                'content' => [
                    'numId' => 'numId'.$numId,
                    'params' => $params
                ],
            ]);
            Db::commit();
            return [
                'num_id' => $numId,
                'nextStep' => $status,
            ];
        }catch (Exception $e)
        {
            Db::rollback();
            $this->error($e->getMessage());
        }
    }

    /**
     * 获取投保方案下一节点状态
     * type:order 投保  insure_file 上传投保单  pay 支付
     */
    public function getOrderStatus($productId, $workId = 0, $type = 'order', $numId = '')
    {
        $product = ProductModel::getInstance()->find($productId);
        $productInfo = ProductInfoModel::getInstance()->column([
            'pro_id' => ['eq', $productId]
        ], 'content', 'field');
        foreach ($productInfo as $k => &$v)
        {
            $v = strpos($v, '{') !== false ? json_decode($v, true) : $v;
        }
        $proInfo = array_merge($product, $productInfo);

        $isInsureFile = !empty($proInfo['is_insure_file']) ? 1 : 0;
        $isAmendsInsureFile = !empty($proInfo['is_amends_insure_file']) ? 1 : 0;

        switch ($type)
        {
            case 'order':
                $isInsureBeforeCheck = WorkTypeModel::getInstance()->value([
                    'id' => ['eq', $workId]
                ], 'is_insure_before_check');
                $status = !empty($isInsureBeforeCheck) ? 13 : ( !empty($isInsureFile) ? ( !empty($isAmendsInsureFile) ? 1 : 11 ) : 1 );
                break;
            case 'insure_file':
                $orderInfo = OrderModel::getInstance()->find($numId);
                $status = $orderInfo['status'] == 11 ? 1 : $orderInfo['status'];
                break;
            case 'pay':
                break;
            case 'correction':
                $status = !empty($isInsureFile) ? ( !empty($isAmendsInsureFile) ? 1 : 11 ) : 1;
                break;
        }
        return $status;
    }

    /**
     * 生成投保文件、人员清单
     */
    public function createInsuredFile($params)
    {
        $productCode = ProductModel::getInstance()->productValue([
            'id' => ['eq', $params['product_id']]
        ], 'product_code');
        $fileConfig = config('fileConfig');

        $fileArr = [];
        if (isset($fileConfig['workFile'][$productCode]))
        {
            $template = 'template';
            switch ($productCode)
            {
                case 'P2104199545':
                    $isHigh = WorkTypeModel::getInstance()->value([
                        'id' => ['eq', $params['workId'][count($params['workId']) - 1]]
                    ], 'is_high');
                    $template = empty($isHigh) ? 'templateA' : 'templateB';
                    break;
            }
            $templateFilePath = $fileConfig['workFile'][$productCode][$template];
            $variable = $fileConfig['workFile'][$productCode]['variable'];
            $source = ROOT_PATH . '/public'.$templateFilePath;
            $templateProcessor = new TemplateProcessor($source);
            foreach ($variable as $k => $v)
            {
                switch ($k)
                {
                    case 'applicationAddress':
                        break;
                    case 'insuredAddress':
                        break;
                    case 'personList':
                        break;
                    case 'liabilityLimit':
                        break;
                    case 'perLiabilityLimit':
                        break;
                    case 'accidentLimit':
                        break;
                    case 'casualtiesLiabilityLimit':
                        break;
                    case 'medicalExpense':
                        break;
                    case 'chargeLoss':
                        break;
                    case 'isHaveBill':
                        break;
                    case 'date':
                        $templateProcessor->setValue($k, $this->stampToDateTime(time()));
                        break;
                    case 'tMonth':
//                        $tMonth = intval(($date2 - $date1)/(3600*24*30));
//                        $tMonth = empty($tMonth) ? 1 : $tMonth;
//                        $t_month = $tMonth.'月，自' . datetime(strtotime($params['order']['s_time']), 'Y年m月d日') . ' 零 时起至' . date('Y年m月d日', strtotime($params['order']['e_time'])) . ' 24 时止。';
                        break;
                    default:
                        $templateProcessor->setValue($k, $params[$v]);
                        break;
                }
            }
            $path = 'uploads/insuredFile/'.datetime(time(), 'Ymd').'_insured/';
            if (!is_dir($path))
            {
                mkdir($path, 0777, true);
            }
            $filePath = $path.iconv('UTF-8', 'GB18030', 'insured_'.$params['numId'].'.doc');
            $templateProcessor->saveAs($filePath);
            $fileArr[] = '/'.$filePath;
        }

        if (isset($fileConfig['excelFile'][$productCode]))
        {
            $templateFilePath = $fileConfig['excelFile'][$productCode]['template'];
            $variable = $fileConfig['excelFile'][$productCode]['variable'];
            $source = ROOT_PATH . '/public'.$templateFilePath;
            $spreadSheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($source);
            $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadSheet);
            foreach ($variable as $k => $v)
            {
                $spreadSheet->setActiveSheetIndex($k);
                $k = $spreadSheet->getActiveSheet();
                foreach ($v as $kk => $vv)
                {
                    switch ($k)
                    {
                        case 'idCard':
                            break;
                        default:
                            $k->setCellValue($vv, $params[$kk]);
                            break;
                    }
                }
            }
            $spreadSheet->setActiveSheetIndex(0);
            $file_path = '/uploads/insuredFile/'.datetime(time(), 'Ymd').'_PersonList/';
            if (!is_dir('.' . $file_path)) {
                @mkdir('.' . $file_path, 0777, true);
            }
            $filePath = $file_path . 'person_' . $params['numId'] . '.xls';
            $writer->save('.'. $filePath);
            $fileArr[] = $filePath;
        }
        return $fileArr;
    }

    /**
     * 批量上传人员清单
     */
    public function getPersonList($params)
    {
        $Validate = new \think\Validate([
            'fileUrl' => 'require',
        ], [
            'fileUrl' => '文件地址无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $domain = Config::get('domain.'.Domain);
        $fileUrl = str_replace($domain['domain'], '', $params['fileUrl']);
        $excel = new Excel();
        $fileData = $excel->reader('.'.$fileUrl);
        unset($fileData[0]);
        foreach ($fileData as $k => &$v)
        {
            if (empty($v[1]))
            {
                unset($fileData[$k]);
            }
        }
        return [
            'fileData' => array_values($fileData)
        ];
    }

    /**
     * 识别批改替换人员模板
     */
    public function getCorrectionPersonXls($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require',
            'fileUrl' => 'require',
        ], [
            'numId' => '订单标识无效',
            'fileUrl' => '文件地址无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $domain = Config::get('domain.'.Domain);
        $fileUrl = str_replace($domain['domain'], '', $params['fileUrl']);
        $excel = new Excel();
        $fileData = $excel->reader('.'.$fileUrl);
        unset($fileData[0]);unset($fileData[1]);unset($fileData[2]);

        $correction = $this->getCorrectionInfo($params);
        $corrMoney = $correction['policyMoney'];

        $recordId = array_unique(OrderEmployeeRecordModel::getInstance()->column([
            'num_id' => ['eq', $params['numId']],
            'status' => ['eq', 1]
        ], 'record_id'));
        $noChangePaperNum = OrderEmployeeRecordModel::getInstance()->column([
            'id' => ['in', $recordId]
        ], 'code');

        $insuredList = OrderEmployeeRecordModel::getInstance()->column([
            'num_id' => ['eq', $params['numId']],
            'status' => ['eq', 1]
        ], 'code');

        $changeInfo = self::getCorrectionInfo([
            'numId' => $params['numId']
        ]);
        $codeArr = array_column($changeInfo['personList'], 'code');

        $addData = $delData = $noChangeData = [];
        foreach ($fileData as $k => &$v)
        {
            if (empty($v[1]))
            {
                unset($fileData[$k]);break;
            }
            $addData[] = [$v[0], $v[1], $v[2]];
            if (!empty($v[4]))
            {
                $key = array_keys($codeArr, $v[4]) ? array_keys($codeArr, $v[4])[0] : '';

                if (in_array($v[4], $noChangePaperNum) || !in_array($v[4], $insuredList) || !$changeInfo['personList'][$key]['isChange'])
                {
                    $noChangeData[] = [$v[3], $v[4]];
                }else{
                    $delData[] = [$v[3], $v[4]];
                }
            }
        }

        if (count($addData) > count($delData) && !$changeInfo['isAdd'])
        {
            $this->error('该订单不允许新增人员');
        }

        return [
            'addData' => $addData,
            'delData' => $delData,
            'noChangeData' => $noChangeData,
            'dataTxt' => '增加：'.count($addData).'人；减少：'.count($delData).'人；不允许替换：'.count($noChangeData).'人；应收保费：'.number_format((count($addData) - count($delData)) * $corrMoney, 2)
        ];
    }

    /**
     * 上传投保资料
     */
    public function uploadInsureFile($params)
    {
        $Validate = new \think\Validate([
            'insureFile' => 'require|array',
            'numId' => 'require',
        ], [
            'insureFile' => '投保资料信息无效',
            'numId' => '订单流水号无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $orderInfo = OrderModel::getInstance()->find($params['numId']);
        $insureFile = json_decode($orderInfo['insure_file'], true);
        $insureFile = empty($insureFile) ? $params['insureFile'] : array_merge($params['insureFile'], $insureFile);
        $status = self::getOrderStatus($orderInfo['product_id'], 0, 'insure_file', $params['numId']);
        $res = OrderModel::getInstance()->update($params['numId'], [
            'insure_file' => json_encode($insureFile),
            'status' => $status
        ]);
        return [
            'nextStep' => $status
        ];
    }

    /**
     * 保单支付
     */
    public function policyPay($params)
    {
        $Validate = new \think\Validate([
            'payType' => 'require',
            'numId' => 'require',
            'payName' => 'require',
            'payVoucher' => 'require|array',
        ], [
            'payType' => '支付方式无效',
            'numId' => '订单流水号无效',
            'payName' => '支付名称无效',
            'payVoucher' => '支付证明无效',
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $orderInfo = OrderModel::getInstance()->find($params['numId']);
        $sTime = ClientProductService::getInstance()->getProductTimeRule([
            'product_id' => $orderInfo['product_id'],
            'identification' => 1
        ]);
        $order['s_time'] = $orderInfo['s_time'];
        $order['e_time'] = $orderInfo['e_time'];

        if ($sTime['startTime'] > $orderInfo['s_time'])
        {
            $order['s_time'] = datetime(strtotime($sTime['startTime']), 'Y-m-d 00:00:00');
            $order['e_time'] = datetime(strtotime($orderInfo['e_time']) + (strtotime($sTime['startTime']) - strtotime($orderInfo['s_time'])), 'Y-m-d 23:59:59');
            OrderEmployeeRecordModel::getInstance()->update([
                'num_id' => ['eq', $params['numId']]
            ], [
                's_time' => $order['s_time'],
                'e_time' => $order['e_time']
            ]);
        }

        $order['pay_money'] = $orderInfo['policy_money'];
        $order['pay_type'] = $params['payType'];
        $order['status'] = 2;//根据流程设定状态值
        if ($params['payType'] == 2)
        {
            $order['pay_voucher'] = json_encode([
                'payName' => $params['payName'],
                'payVoucher' => $params['payVoucher'],
                'payTime' => $this->stampToDateTime(time()),
                'payCardCode' => isset($params['payCardCode']) ? $params['payCardCode'] : '',
            ]);
            return OrderModel::getInstance()->update($params['numId'], $order);
        }else{
            $this->error('线上支付待对接');
        }
    }

    /**
     * 获取保单详情
     */
    public function getOrderInfo($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require',
        ], [
            'numId' => '订单流水号无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $info = OrderModel::getInstance()->find($params['numId']);
        $plan = json_decode($info['product_plan'], true);
        $proInfo = ProductModel::getInstance()->find($plan['product_id'], 'company, payment_method');
        $companyId = $proInfo['company'];
        $companyName = CompanyModel::getInstance()->value([
            'id' => ['eq', $companyId]
        ], 'name');
        $zipFile = '';
        if (!empty($info['insure_file']))
        {
            $zipFile = ZipService::getInstance()->createZip(json_decode($info['insure_file'], true), '投保资料'.rand(1000,9999));
        }
        $companyBackInfo = CompanyModel::getInstance()->find($companyId, 'bank_no, bank_name, bank_title');
        $companyBackInfo = empty($companyBackInfo) ? [] : $companyBackInfo;
        $payVoucher = !empty($info['pay_voucher']) ? json_decode($info['pay_voucher'], true) : [];

        /***/
        if ($info['status'] == 3)
        {
            if ($info['s_time'] > $this->stampToDateTime(time()))
            {
                $info['status'] = 5;
            }
            if ($info['s_time'] <= $this->stampToDateTime(time()))
            {
                $info['status'] = 6;
            }
        }
        if (in_array($info['status'], [3,5,6]) && $info['e_time'] < datetime(time(), 'Y-m-d H:i:s'))
        {
            $info['status'] = 7;
        }
        $info['status'] = $info['status'] == 3 ? (empty($info['policy_num']) || empty($info['policy_file']) ? 15 : ( !empty($info['is_have_bill']) && empty($info['bill_file']) ? 15 : $info['status'] )) : $info['status'];
        /***/
        $info['status'] = $info['status'] == 6 ? (empty($info['policy_num']) || empty($info['policy_file']) ? 5 : 6) : $info['status'];

        $agentId = AgentCompanyModel::getInstance()->value([
            'pro_id' => ['like', '%'.$plan['product_id'].'%']
        ], 'agent_id');
        $agentName = AgentModel::getInstance()->value([
            'id' => ['eq', $agentId]
        ], 'title');

        $info['bill_file'] = str_replace(' ', '', $info['bill_file']);
        return [
            'adminName' => AdminModel::getInstance()->value([
                'id' => ['eq', $info['admin_id']]
            ], 'nickname'),
            'applicationName' => OrderApplicationModel::getInstance()->value($params['numId'], 'name'),
            'numId' => $params['numId'],
            'policyNum' => $info['policy_num'],
            'policyMoney' => $info['policy_money'],
            'cTime' => $info['c_time'],
            'sTime' => $info['s_time'],
            'eTime' => $info['e_time'],
            'agent_id' => $agentId,
            'agent_name' => $agentName,
            'workCate' => $info['work_cate_title'],
            'workType' => $info['work_type_title'],
            'policyFile' => empty($info['policy_file']) ? null : $info['policy_file'],
            'billFile' => empty($info['bill_file']) ? null : $info['bill_file'],
            'insureFile' => $zipFile,
            'is_have_bill' => $info['is_have_bill'],
            'companyName' => $companyName,
            'paymentMethod' => empty($info['pay_type']) ? $proInfo['payment_method'] : $info['pay_type'],
            'payVoucher' => array_merge($companyBackInfo, $payVoucher),
            'plan' => [
                'productName' => ''.ProductModel::getInstance()->productValue([
                    'id' => ['eq', $plan['product_id']]
                ], 'product_name'),
                'scheme_code' => ''.$plan['scheme_code'],
                'disabRatio' => isset($plan['disabRatio']) ? ($plan['disabRatio'] == 'is_five_percent' ? '十级5%' : ($plan['disabRatio'] == 'is_one_percent' ? '十级1%' : '十级10%')) : '十级5%',
                'isAllDays' => !empty($plan['isAllDays']) ? '扩展24小时' : '',
                'death_quota' => '死亡、伤残限额：'.$plan['death_quota'].'万元',
                'medical_quota' => '医疗责任限额：'.$plan['medical_quota'].'万元',
                'loss_work_cost' => '误工费：'.$plan['loss_work_cost'].'元/天',
                'hospital_allowance' => '住院津贴：'.$plan['hospital_allowance'].'元/天',
                'legal_fees' => '法律费用：'.$plan['legal_fees'].'元',
            ],
            'status' => $info['status'],
            'statusTxt' => $this->uStatus[$info['status']],
            'isChange' => in_array($info['status'], [3,5,6]) && $info['s_time'] <= datetime(time(), 'Y-m-d H:i:s') ? 1 : 0
        ];
    }

    /**
     * 获取投、被保人信息
     */
    public function getOrderInsured($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require',
        ], [
            'numId' => '订单流水号无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $application = OrderApplicationModel::getInstance()->find($params['numId'], 'name,code,province,city,area,address,phone,code_img,legal_person,business_site');
        $insured = OrderInsuredModel::getInstance()->find($params['numId'], 'name,code,province,city,area,address,phone,code_img,legal_person,business_site');
        $application['provinceName'] = CommonService::getInstance()->getAreaName($application['province']);
        $application['cityName'] = CommonService::getInstance()->getAreaName($application['city']);
        $application['areaName'] = CommonService::getInstance()->getAreaName($application['area']);
        $insured['provinceName'] = CommonService::getInstance()->getAreaName($insured['province']);
        $insured['cityName'] = CommonService::getInstance()->getAreaName($insured['city']);
        $insured['areaName'] = CommonService::getInstance()->getAreaName($insured['area']);
        return [
            'application' => $application,
            'insure' => $insured
        ];
    }

    /**
     * 获取订单开票信息
     */
    public function getOrderInvoice($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require'
        ], [
            'numId' => '订单流水号无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $invoice = OrderInvoiceModel::getInstance()->find($params['numId'], 'taxpayer_name,type,taxpayer_id,taxpayer_addr,taxpayer_tel,taxpayer_bank,taxpayer_bankno,ext_info,invoice_phone,address,new_contact_name');
        $invoice['ext_info'] = json_decode($invoice['ext_info'], true);
        return $invoice;
    }

    /**
     * 获取保障人员列表
     */
    public function getOrderPersonnel($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require',
            'type' => 'require|number'
        ], [
            'numId' => '订单流水号无效',
            'type' => '人员状态标识无效'// 1 在保  2 过保  3 待生效
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $where = [
            'num_id' => ['eq', $params['numId']],
            'status' => ['eq', 1]
        ];
        $correctIds = OrderCorrectRecordModel::getInstance()->column([
            'status' => ['in', [3,5,6,7]],
            'num_id' => ['eq', $params['numId']]
        ], 'id');
        $correctIds[] = 0;
        $oInfo = OrderModel::getInstance()->find($params['numId'], 'status,policy_file,policy_num');
        $where['change_id'] = ['in', $correctIds];
        switch ($params['type'])
        {
            case 1:
                if ($oInfo['status'] == 2 || empty($oInfo['policy_num']) || empty($oInfo['policy_file']))
                {
                    $record = OrderEmployeeRecordModel::getInstance()->column([
                        'change_id' => ['eq', 0],
                        'num_id' => ['eq', $params['numId']]
                    ], 'id');
                    $where['id'] = ['NOT IN', $record];
                }
                $where['s_time'] = ['elt', $this->stampToDateTime(time())];
                $where['e_time'] = ['egt', $this->stampToDateTime(time())];
                break;
            case 2:
                $where['s_time'] = ['lt', $this->stampToDateTime(time())];
                $where['e_time'] = ['lt', $this->stampToDateTime(time())];
                break;
            case 3:
                $status = OrderModel::getInstance()->value($params['numId'], 'status');
                if ($status == 4)
                {
                    $where['status'] = ['in', [0,1]];
                }else{
                    if ($oInfo['status'] == 2 || empty($oInfo['policy_num']) || empty($oInfo['policy_file']))
                    {
                        $record = OrderEmployeeRecordModel::getInstance()->column([
                            'change_id' => ['eq', 0],
                            'num_id' => ['eq', $params['numId']]
                        ], 'id');
                        $where['id'] = ['IN', $record];
                    }else{
                        $where['s_time'] = ['gt', $this->stampToDateTime(time())];
                        $where['e_time'] = ['gt', $this->stampToDateTime(time())];
                    }
                }

                break;
        }

        $list = OrderEmployeeRecordModel::getInstance()->select($where, 'id,change_id,record_id,name,code,money,s_time,e_time,work_cate_title,work_type_title');
        return $list;
    }

    /**
     * 获取订单记录
     */
    public function getOrderList($params)
    {
        $identification = $this->request->param('identification', 1);
        $page = $this->request->param('page', 1);
        $limit = $this->request->param('limit', 15);
        $start = ($page - 1) * $limit;
        $adminIds[] = $this->uid;
        if ($identification == 2 || $identification == 3)
        {
            $thisAdminIds = array_column(AdminService::getInstance()->getAdmin([], true), 'id');
            $adminIds = array_merge($adminIds, $thisAdminIds);
            $teamIds = AdminModel::getInstance()->value([
                'id' => ['eq', $this->uid]
            ], 'team');
            $teamAdminIds = AdminModel::getInstance()->column([
                'team' => ['eq', $teamIds]
            ], 'id');
            $adminIds = array_unique(array_merge($adminIds, $teamAdminIds));
        }
        $where = [
            'admin_id' => ['in', $adminIds]
        ];

        if (!empty($params['company_id']))
        {
            $proIds = ProductModel::getInstance()->column([
                'company' => ['eq', $params['company_id']]
            ]);
            $where['product_id'] = ['in', $proIds];
        }

        if (!empty($params['numId']))
        {
            $where['num_id'] = ['like', '%'.$params['numId'].'%'];
        }
        if (!empty($params['policyNum']))
        {
            $where['policy_num'] = ['like', '%'.$params['policyNum'].'%'];
        }
        if (!empty($params['sTimeArr']))
        {
            $where['s_time'] = ['between', [$params['sTimeArr'][0], $params['sTimeArr'][1]]];
        }
        if (!empty($params['cTimeArr']))
        {
            $where['c_time'] = ['between', [$params['cTimeArr'][0], $params['cTimeArr'][1]]];
        }
        if (isset($params['adminId']))
        {
            $where['admin_id'] = ['eq', $params['adminId']];
        }
        if (!empty($params['applicationName']))
        {
            $numIds = OrderApplicationModel::getInstance()->column([
                'name' => ['like', '%'.$params['applicationName'].'%']
            ], 'num_id');
            $where['num_id'] = ['in', $numIds];
        }
        if (!empty($params['insuredName']))
        {
            $numIds = OrderInsuredModel::getInstance()->column([
                'name' => ['like', '%'.$params['insuredName'].'%']
            ], 'num_id');
            $where['num_id'] = ['in', $numIds];
        }
        $whereOr = [];
        if (!empty($params['status']))
        {
            switch ($params['status'])
            {
                case 15:
                    $where['status'] = ['eq', 3];
                    $isNullPolicyNum = OrderModel::getInstance()->column([
                        'status' => ['eq', 3],
                        'policy_num' => ['null', 'null']
                    ], 'id');
                    $isNullPolicyFile = OrderModel::getInstance()->column([
                        'status' => ['eq', 3],
                        'policy_file' => ['null', 'null']
                    ], 'id');
                    $isNullBillFile = OrderModel::getInstance()->column([
                        'status' => ['eq', 3],
                        'bill_file' => ['null', 'null']
                    ], 'id');
                    $isNullIds = array_merge($isNullPolicyNum, $isNullPolicyFile, $isNullBillFile);
                    $where['id'] = ['in', $isNullIds];
                    $where['e_time'] = ['gt', $this->stampToDateTime(time())];
                    break;
                case 3:
                    $where['status'] = ['in', [3,4,5,6]];
                    break;
                case 5:
                    $noFile = OrderModel::getInstance()->column([
                        'policy_file' => ['null', 'null'],
                        'status' => ['in', [3,5,6]],
                        'e_time' => ['gt', $this->stampToDateTime(time())]
                    ], 'id');
                    $noNum = OrderModel::getInstance()->column([
                        'policy_num' => ['null', 'null'],
                        'status' => ['in', [3,5,6]],
                        'e_time' => ['gt', $this->stampToDateTime(time())]
                    ], 'id');
                    $endTime = OrderModel::getInstance()->column([
                        's_time' => ['gt', $this->stampToDateTime(time())],
                        'status' => ['in', [3,5,6]]
                    ], 'id');
                    $where['status'] = ['in', [3,5,6]];
                    $where['id'] = ['in', array_merge($noFile, $noNum, $endTime)];
                    break;
                case 6:
                    $where['status'] = ['in', [3,5,6]];
                    $where['s_time'] = ['elt', $this->stampToDateTime(time())];
                    $where['e_time'] = ['egt', $this->stampToDateTime(time())];
                    $where['policy_num'] = ['notnull', 'notnull'];
                    $where['policy_file'] = ['notnull', 'notnull'];
                    break;
                case 7:
                    $where['status'] = ['in', [3,5,6]];
                    $where['e_time'] = ['lt', $this->stampToDateTime(time())];
                    break;
                default:
                    $where['status'] = ['eq', $params['status']];
                    break;
            }
        }

        $list = OrderModel::getInstance()->select($where, 'num_id,admin_id,policy_num,policy_file,bill_file,is_have_bill,policy_money,s_time,e_time,c_time,product_id,work_cate_title,work_type_title,status', $start, $limit, $whereOr);

        $orderApplication = OrderApplicationModel::getInstance()->column([
            'num_id' => ['in', array_column($list, 'num_id')]
        ]);
        $orderInsured = OrderInsuredModel::getInstance()->column([
            'num_id' => ['in', array_column($list, 'num_id')]
        ]);

        $proList = ProductModel::getInstance()->column([
            'id' => ['in', array_column($list, 'product_id')]
        ], 'product_name,company');
        $companyList = CompanyModel::getInstance()->column([
            'id' => ['in', array_column($proList, 'company')]
        ], 'name');
        $admin = AdminModel::getInstance()->column([], 'nickname');

        foreach ($list as $k => &$v)
        {
            if ($v['status'] == 3 && $identification != 2)
            {
                if ($v['s_time'] > $this->stampToDateTime(time()))
                {
                    $v['status'] = 5;
                }
                if ($v['s_time'] <= $this->stampToDateTime(time()))
                {
                    $v['status'] = 6;
                }
                if (empty($v['policy_file']) || empty($v['policy_num']))
                {
                    $v['status'] = 5;
                }
            }
            if (in_array($v['status'], [3,5,6]) && $v['e_time'] < datetime(time(), 'Y-m-d H:i:s'))
            {
                $v['status'] = 7;
            }
            $v['status'] = $v['status'] == 3 ? (empty($v['policy_num']) || empty($v['policy_file']) ? 15 : ( !empty($v['is_have_bill']) && empty($v['bill_file']) ? 15 : $v['status'] )) : $v['status'];
            $v['productName'] = $proList[$v['product_id']]['product_name'];
            $v['companyName'] = $companyList[$proList[$v['product_id']]['company']];
            $v['statusTxt'] = $identification == 2 ? $this->status[$v['status']] : $this->uStatus[$v['status']];
            $v['applicationName'] = $orderApplication[$v['num_id']];
            $v['insuredName'] = $orderInsured[$v['num_id']];
            $v['isChange'] = $v['status'] == 6 ? 1 : 0;
            $v['adminName'] = $admin[$v['admin_id']];
        }
        return [
            'total' => OrderModel::getInstance()->count($where, $whereOr),
            'list' => $list
        ];
    }

    /**
     * 保单审核
     */
    public function orderCheck($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require',
            'type' => 'require',
        ], [
            'numId' => '订单流水号无效',
            'type' => '审核状态无效'// 1 审核通过  2 驳回
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }

        Db::startTrans();
        try{
            if ($params['type'] == 2)
            {
                OrderModel::getInstance()->update($params['numId'], [
                    'status' => 4
                ]);
                OrderEmployeeRecordModel::getInstance()->update([
                    'num_id' => ['eq', $params['numId']]
                ], [
                    'status' => 0
                ]);
                $res = true;
            }else{
                //修改保单状态  根据流程 识别下一步状态    打包投保资料 发送到保司
                $orderInfo = OrderModel::getInstance()->find($params['numId'], 'insure_file,product_id,buy_count,s_time,e_time,is_have_bill');
                $companyId = ProductModel::getInstance()->productValue([
                    'id' => ['eq', $orderInfo['product_id']]
                ], 'company');
                $toEmail = CompanyModel::getInstance()->find($companyId, 'insure_email,insure_email_spare');
                $toEmail = array_values($toEmail);

                //邮件标题： **方案 十级*% 新单 投保N人 保障期限 N - N  专票、普票、不开票
                $emailTitle = '';
                $proInfo = ProductModel::getInstance()->find($orderInfo['product_id'], 'product_name');
                $emailTitle .= $proInfo['product_name'] . ' 新单 投保'.$orderInfo['buy_count'].'人 保障期限'.$orderInfo['s_time'].'至'.$orderInfo['e_time'];
                $invoiceTitle = ' 不开票';
                if ($orderInfo['is_have_bill'])
                {
                    $invoiceType = OrderInvoiceModel::getInstance()->value($params['numId'], 'type');
                    $invoiceTitle = $invoiceType == 2 ? ' 专票' : ' 普票';
                }
                $emailTitle .= $invoiceTitle;
                if (!empty($orderInfo['insure_file']))
                {
                    $emailData = [
                        'toEmail' => implode(',', $toEmail),
                        'title' => $emailTitle,
                        'isZip' => true,
                        'files' => json_decode($orderInfo['insure_file'], true)
                    ];
                    EmsService::getInstance()->sendEmail($emailData);
                }
                OrderEmployeeRecordModel::getInstance()->update([
                    'num_id' => ['eq', $params['numId']]
                ], [
                    'status' => 1
                ]);
                $res = OrderModel::getInstance()->update($params['numId'], [
                    'status' => 3
                ]);
                /*switch ($companyId)
                {
                    case 4:
                        HbPiccService::getInstance()->insure($params['numId']);
                        break;
                }*/
            }
            LogService::getInstance()->writeSysLog([
                'operation' => '/api/order/orderCheck',
                'title' => '保单审核'.($params['type'] == 2 ? '驳回' : '通过').'  '.(isset($params['desc']) ? $params['desc'] : ''),
                'content' => [
                    'numId' => 'numId'.$params['numId'],
                    'params' => $params
                ],
            ]);
            Db::commit();
            return $res;
        }catch (Exception $e)
        {
            Db::rollback();
            $this->error($e->getMessage());
        }
    }

    /**
     * 获取起保日期、是否可增加人员、可替换人员列表、基础保费
     */
    public function getCorrectionInfo($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require'
        ], [
            'numId' => '订单流水号无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $orderInfo = OrderModel::getInstance()->find($params['numId']);
        $sTime = ClientProductService::getInstance()->getProductTimeRule([
            'product_id' => $orderInfo['product_id'],
            'identification' => 2
        ]);
        $Guarantee = self::getMonthDiff($orderInfo['s_time'], $orderInfo['e_time']);
        $Guarantee = $Guarantee[1] + ($Guarantee[2] ? 1 : 0);
        $productRule = ProductRuleModel::getInstance()->find($orderInfo['product_id']);
        $insureRule = json_decode($productRule['insure_rule'], true);

        $isAdd = $insureRule['is_add_person'][array_search($Guarantee, $insureRule['month'])];
        $isChange = $insureRule['is_change_person'][array_search($Guarantee, $insureRule['month'])];
        $personList = self::getChangePersonList($params, $isChange);

        $insureTime = isset($params['insureTime']) ? $params['insureTime'] : $sTime['startTime'];
        $changeGuarantee = self::getMonthDiff(datetime(strtotime($insureTime) - 3600 * 24, 'Y-m-d 00:00:00'), $orderInfo['e_time']);
        $changeGuarantee = $changeGuarantee[1] + ($changeGuarantee[2] ? 1 : 0);

        if ($insureRule['is_month_rate'])
        {
            //日費率  新单保费/保障天数   *   批改剩余天数  *  批改日费率  / 100
            $policyMoney = ( ($orderInfo['policy_money'] / $orderInfo['buy_count'] / ceil(( (strtotime($orderInfo['e_time']) - strtotime($orderInfo['s_time'])) / 24 / 3600 ))) *  ceil(( (strtotime($orderInfo['e_time']) - strtotime($insureTime)) / 24 / 3600 )) ) * ($insureRule['correct_rate'][array_search($changeGuarantee, $insureRule['month'])]) / 100;
        }else{
            //月費率  年保费 * 批改剩余月份费率 / 100
            $policyMoney = ( ($orderInfo['policy_money'] / $orderInfo['buy_count']) / $insureRule['month_rate'][array_search($Guarantee, $insureRule['month'])] * 100 ) * $insureRule['correct_rate'][array_search($changeGuarantee, $insureRule['month'])] / 100;
        }
        $companyId = ProductModel::getInstance()->productValue([
            'id' => ['eq', $orderInfo['product_id']]
        ], 'company');
        $companyInfo = CompanyModel::getInstance()->find($companyId);
        return [
            'startTime' => $sTime['startTime'],
            'endTime' => $sTime['endTime'],
            'isAdd' => $isAdd,
            'personList' => $personList,
            'policyMoney' => $policyMoney + 0.00000001,
            'premiumSetting' => $companyInfo['premium_setting'],
            'premiumRule' => $companyInfo['premium_rule'],
        ];
    }

    /**
     * 获取可替换在保人员列表
     */
    public function getChangePersonList($params, $isChange = 1)
    {
        $Validate = new \think\Validate([
            'numId' => 'require'
        ], [
            'numId' => '订单流水号无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        //在保人员
        $insure = self::getOrderPersonnel([
            'numId' => $params['numId'],
            'type' => 1
        ]);
        //待生效人员
        $insured = self::getOrderPersonnel([
            'numId' => $params['numId'],
            'type' => 3
        ]);
        foreach ($insure as $k => &$v)
        {
            $v['isChange'] = $isChange ? (in_array($v['id'], array_column($insured, 'record_id')) ? 0 : 1) : 0;
        }
        return $insure;
    }

    /**
     * 申请批改
     */
    public function orderCorrection($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require',
            'insureTime' => 'require',
            'addPerson' => 'require',
        ], [
            'numId' => '订单流水号无效',
            'insureTime' => '起保日期无效',
            'addPerson' => '新增人员信息无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $checkData = [
            'name' => 'require',
            'idCard' => 'require'
        ];
        $checkMsg = [
            'name' => '批改人员姓名必填',
            'idCard' => '批改人员证件号无效'
        ];
        $Validate = new \think\Validate($checkData, $checkMsg);
        foreach ($params['addPerson'] as $k => $v)
        {
            if (!$Validate->check($v))
            {
                $this->error($Validate->getError());
            }
        }
        $delPerson = [];
        if (isset($params['delPerson']))
        {
            $delPerson = $params['delPerson'];
            $checkData['changeId'] = 'require';
            $checkMsg['changeId'] = '被替换人员标识无效';
            $Validate = new \think\Validate($checkData, $checkMsg);
            foreach ($params['delPerson'] as $k => $v)
            {
                if (!$Validate->check($v))
                {
                    $this->error($Validate->getError());
                }
            }
        }
        Db::startTrans();
        try{
            $timeAndMoney = self::getCorrectionInfo($params);
            $orderInfo = OrderModel::getInstance()->find($params['numId']);
            $addNum = count($params['addPerson']) - count($delPerson);
            $status = self::getOrderStatus($orderInfo['product_id'], 0, 'correction');
            $status = $status == 11 ? $status : ( $addNum ? 1 : 2 );
            $correctData = [
                'admin_id' => $this->uid,
                'num_id' => $params['numId'],
                'policy_num' => $orderInfo['policy_num'],
                'policy_money' => $timeAndMoney['policyMoney'] * $addNum,
                'add_num' => count($params['addPerson']),
                'change_num' => count($delPerson),
                'status' => $status,
                's_time' => $params['insureTime'],
                'e_time' => $orderInfo['e_time'],
                'is_have_bill' => $orderInfo['is_have_bill'],
                'work_cate_title' => $orderInfo['work_cate_title'],
                'work_type_title' => $orderInfo['work_type_title'],
                'c_time' => datetime(time(), 'Y-m-d H:i:s')
            ];
            $correctId = OrderCorrectRecordModel::getInstance()->insert($correctData);
            $employeeRecord = array_merge($params['addPerson'], []);
            $changeIds = array_column($delPerson, 'changeId');
            foreach ($employeeRecord as $k => $v)
            {
                $recordData[] = [
                    'num_id' => $params['numId'],
                    'change_id' => $correctId,
                    'record_id' => isset($changeIds[$k]) ? $changeIds[$k] : 0,
                    'name' => $v['name'],
                    'code' => $v['idCard'],
                    'type' => 1,
                    'money' => $timeAndMoney['policyMoney'],
                    's_time' => $params['insureTime'],
                    'e_time' => $orderInfo['e_time'],
                    'work_cate_title' => $orderInfo['work_cate_title'],
                    'work_type_title' => $orderInfo['work_type_title'],
                    'status' => 1,
                ];
            }
            $res = OrderEmployeeRecordModel::getInstance()->insertAll($recordData);
            LogService::getInstance()->writeSysLog([
                'operation' => '/api/order/orderCorrection',
                'title' => '申请批改: 批改ID'.$correctId,
                'content' => [
                    'changeId' => 'changeId'.$correctId,
                    'params' => $params
                ],
            ]);
            Db::commit();
            return [
                'changeId' => $correctId,
                'nextStep' => $status
            ];
        }catch (Exception $e)
        {
            Db::commit();
            $this->error($e->getMessage());
        }
    }

    /**
     * 获取批改列表
     */
    public function getCorrectionList($params)
    {
        $Validate = new \think\Validate([
            'identification' => 'require',
        ], [
            'identification' => '查询标识无效'// 1 批改列表  2 批改审核列表
        ]);

        $page = $this->request->param('page', 1);
        $limit = $this->request->param('limit', 15);
        $start = ($page - 1) * $limit;

        $where = $params['identification'] == 2 ? [
            'status' => ['eq', 2]
        ] : [
            'admin_id' => ['eq', $this->uid]
        ];
        if ($params['identification'] == 2 || $params['identification'] == 3)
        {
            $adminIds[] = $this->uid;
            $thisAdminIds = array_column(AdminService::getInstance()->getAdmin([], true), 'id');
            $adminIds = array_merge($adminIds, $thisAdminIds);
            $teamIds = AdminModel::getInstance()->value([
                'id' => ['eq', $this->uid]
            ], 'team');
            $teamAdminIds = AdminModel::getInstance()->column([
                'team' => ['eq', $teamIds]
            ], 'id');
            $adminIds = array_unique(array_merge($adminIds, $teamAdminIds));
            $where['admin_id'] = ['in', $adminIds];
        }

        $isNumIds = false;
        $policyNumIds = [];
        if (isset($params['policyNum']))
        {
            $policyNumIds[] = Db::name('order')->where([
                'policy_num' => ['like', '%'.$params['policyNum'].'%']
            ])->value('num_id');
            $isNumIds = true;
        }
        if (isset($params['correctNum']))
        {
            $where['correct_num'] = ['like', '%'.$params['correctNum'].'%'];
        }
        $applicationNumIds = [];
        if (!empty($params['applicationName']))
        {
            $applicationNumIds = OrderApplicationModel::getInstance()->column([
                'name' => ['like', '%'.$params['applicationName'].'%']
            ], 'num_id');
            $isNumIds = true;
        }
        $insuredNumIds = [];
        if (!empty($params['insuredName']))
        {
            $insuredNumIds = OrderInsuredModel::getInstance()->column([
                'name' => ['like', '%'.$params['insuredName'].'%']
            ], 'num_id');
            $isNumIds = true;
        }
        $companyNumIds = [];
        if (isset($params['company_id']))
        {
            $productIds = ProductModel::getInstance()->column([
                'company' => ['eq', $params['company_id']]
            ], 'id');
            $companyNumIds = OrderModel::getInstance()->column([
                'product_id' => ['in', $productIds]
            ], 'num_id');
            $isNumIds = true;
        }
        $numIds = array_merge($policyNumIds, $applicationNumIds, $insuredNumIds, $companyNumIds);
        $diffNumIds = array_unique($numIds);
        $numIds = count($numIds) == count($diffNumIds) ? $numIds : array_diff($numIds, $diffNumIds);
        if ($isNumIds)
        {
            $where['num_id'] = ['in', $numIds];
        }
        if (isset($params['numId']))
        {
            $where['num_id'] = ['like', '%'.$params['numId'].'%'];
        }
        if (!empty($params['sTimeArr']))
        {
            $where['s_time'] = ['between', [$params['sTimeArr'][0], $params['sTimeArr'][1]]];
        }
        if (!empty($params['cTimeArr']))
        {
            $where['c_time'] = ['between', [$params['cTimeArr'][0], $params['cTimeArr'][1]]];
        }
        if (isset($params['adminId']))
        {
            $where['admin_id'] = ['eq', $params['adminId']];
        }
        $whereOr = [];
        if (isset($params['status']))
        {
            switch ($params['status'])
            {
                case 15:
                    $isNullCorrectNum = OrderCorrectRecordModel::getInstance()->column([
                        'status' => ['eq', 3],
                        'correct_num' => ['null', 'null']
                    ], 'id');
                    $isNullPolicyFile = OrderCorrectRecordModel::getInstance()->column([
                        'status' => ['eq', 3],
                        'policy_file' => ['null', 'null']
                    ], 'id');
                    $isNullBillFile = OrderCorrectRecordModel::getInstance()->column([
                        'status' => ['eq', 3],
                        'bill_file' => ['null', 'null']
                    ], 'id');
                    $isNullIds = array_merge($isNullCorrectNum, $isNullPolicyFile, $isNullBillFile);
                    $where['status'] = ['eq', 3];
                    $where['id'] = ['in', $isNullIds];
                    $where['e_time'] = ['gt', $this->stampToDateTime(time())];
                    break;
                case 3:
                    $where['status'] = ['in', [3,4,5,6]];
                    break;
                case 5:
                    $noFile = OrderCorrectRecordModel::getInstance()->column([
                        'policy_file' => ['null', 'null'],
                        'status' => ['in', [3,5,6]],
                        'e_time' => ['gt', $this->stampToDateTime(time())]
                    ], 'id');
                    $noNum = OrderCorrectRecordModel::getInstance()->column([
                        'correct_num' => ['null', 'null'],
                        'status' => ['in', [3,5,6]],
                        'e_time' => ['gt', $this->stampToDateTime(time())]
                    ], 'id');
                    $endTime = OrderCorrectRecordModel::getInstance()->column([
                        's_time' => ['gt', $this->stampToDateTime(time())],
                        'status' => ['in', [3,5,6]]
                    ], 'id');
                    $isNullIds = array_merge($noFile, $noNum, $endTime);
                    $where['status'] = ['in', [3,5,6]];
                    $where['id'] = ['in', $isNullIds];
                    break;
                case 6:
                    $where['status'] = ['in', [3,5,6]];
                    $where['s_time'] = ['elt', $this->stampToDateTime(time())];
                    $where['e_time'] = ['egt', $this->stampToDateTime(time())];
                    $where['correct_num'] = ['notnull', 'notnull'];
                    $where['policy_file'] = ['notnull', 'notnull'];
                    break;
                case 7:
                    $where['status'] = ['in', [3,5,6]];
                    $where['e_time'] = ['lt', datetime(time(), 'Y-m-d H:i:s')];
                    break;
                default:
                    $where['status'] = ['eq', $params['status']];
                    break;
            }
        }

        $list = OrderCorrectRecordModel::getInstance()->select($where, 'id,admin_id,num_id,correct_num,policy_num,policy_money,policy_file,bill_file,status,s_time,e_time,work_cate_title,work_type_title,c_time', $start, $limit, $whereOr);
        $adminList = AdminModel::getInstance()->column([], 'nickname');
        $applicationList = OrderApplicationModel::getInstance()->column([
            'num_id' => ['in', array_column($list, 'num_id')]
        ], 'name');
        $insuredList = OrderInsuredModel::getInstance()->column([
            'num_id' => ['in', array_column($list, 'num_id')]
        ],'name');
        $proIds = OrderModel::getInstance()->column([
            'num_id' => ['in', array_column($list, 'num_id')]
        ], 'product_id');
        $proName = ProductModel::getInstance()->column([
            'id' => ['in', $proIds]
        ], 'product_name,company');
        $companyName = CompanyModel::getInstance()->column([
            'id' => ['in', array_column($proName, 'company')]
        ], 'name');
        foreach ($list as $k => &$v)
        {
            if ($v['status'] == 3 && $params['identification'] != 2)
            {
                if ($v['s_time'] > $this->stampToDateTime(time()))
                {
                    $v['status'] = 5;
                }
                if ($v['s_time'] <= $this->stampToDateTime(time()))
                {
                    $v['status'] = 6;
                }
                if (empty($v['policy_file']) || empty($v['correct_num']))
                {
                    $v['status'] = 5;
                }
            }

            if (in_array($v['status'], [3,5,6]) && $v['e_time'] < datetime(time(), 'Y-m-d H:i:s'))
            {
                $v['status'] = 7;
            }
            $isHaveBill = OrderModel::getInstance()->value($v['num_id'], 'is_have_bill');
            $v['status'] = $v['status'] == 3 ? (empty($v['correct_num']) || empty($v['policy_file']) ? 15 : (!empty($isHaveBill) && empty($v['bill_file']) ? 15 : $v['status'])) : $v['status'];
            $v['adminName'] = $adminList[$v['admin_id']];
            $v['statusTxt'] = $params['identification'] == 2 ? $this->status[$v['status']] : $this->uStatus[$v['status']];
            $v['applicationName'] = isset($applicationList[$v['num_id']]) ? $applicationList[$v['num_id']] : '';
            $v['insuredName'] = isset($insuredList[$v['num_id']]) ? $insuredList[$v['num_id']] : '';
            $v['productName'] = $proName[$proIds[$v['num_id']]]['product_name'];
            $v['companyName'] = $companyName[$proName[$proIds[$v['num_id']]]['company']];
        }

        return [
            'total' => OrderCorrectRecordModel::getInstance()->count($where, $whereOr),
            'list' => $list
        ];
    }

    /**
     * 获取批改详情
     */
    public function getCorrection($params)
    {
        $Validate = new \think\Validate([
            'changeId' => 'require',
        ], [
            'changeId' => '批改标识无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $info = OrderCorrectRecordModel::getInstance()->find([
            'id' => ['eq', $params['changeId']]
        ], 'id,admin_id,num_id,correct_num,policy_num,policy_money,add_num,change_num,status,s_time,e_time,correct_file,policy_file,pay_voucher,is_have_bill,bill_file,work_cate_title,work_type_title,c_time');

        $proId = OrderModel::getInstance()->value($info['num_id'], 'product_id');
        $proName = ProductModel::getInstance()->productValue([
            'id' => ['eq', $proId]
        ], 'product_name');
        $applicationName = OrderApplicationModel::getInstance()->value($info['num_id'], 'name');
        $insuredName = OrderInsuredModel::getInstance()->value($info['num_id'], 'name');
        $info['applicationName'] = $applicationName;
        $info['insuredName'] = $insuredName;
        $info['productName'] = $proName;
        $info['companyName'] = CompanyModel::getInstance()->value([
            'id' => ['eq', ProductModel::getInstance()->productValue([
                'id' => ['eq', $proId]
            ], 'company')]
        ], 'name');
        $info['adminName'] = AdminModel::getInstance()->value([
            'id' => ['eq', $info['admin_id']]
        ], 'nickname');
        $info['payVoucher'] = json_decode($info['pay_voucher'], true);
        $info['bill_file'] = str_replace(' ', '', $info['bill_file']);
        $info['bill_file'] = empty($info['bill_file']) ? null : $info['bill_file'];
        $info['policy_file'] = empty($info['policy_file']) ? null : $info['policy_file'];
        /***/
        if ($info['status'] == 3)
        {
            if ($info['s_time'] > $this->stampToDateTime(time()))
            {
                $info['status'] = 5;
            }
            if ($info['s_time'] <= $this->stampToDateTime(time()))
            {
                $info['status'] = 6;
            }
        }
        if (in_array($info['status'], [3,5,6]) && $info['e_time'] < datetime(time(), 'Y-m-d H:i:s'))
        {
            $info['status'] = 7;
        }
        $info['status'] = $info['status'] == 3 ? (empty($info['correct_num']) || empty($info['correct_file']) ? 15 : $info['status']) : $info['status'];
        $info['statusTxt'] = $this->uStatus[$info['status']];
        /***/

        if (!empty($info['correct_file']))
        {
            $zipFile = ZipService::getInstance()->createZip(json_decode($info['correct_file'], true), '批单资料'.rand(1000,9999));
            $info['correct_file'] = $zipFile;
        }
        return $info;
    }

    /**
     * 批单上传批改资料
     */
    public function uploadCorrectionFile($params)
    {
        $Validate = new \think\Validate([
            'changeId' => 'require',
            'fileUrl' => 'require'
        ], [
            'changeId' => '批单标识无效',
            'fileUrl' => '批改资料无效，请确认上传信息是否完整'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $correctFile = OrderCorrectRecordModel::getInstance()->value([
            'id' => ['eq', $params['changeId']]
        ]);
        $correctFile = !empty($correctFile) ? array_merge(json_decode($correctFile, true), $params['fileUrl']) : $params['fileUrl'];
        OrderCorrectRecordModel::getInstance()->update([
            'id' => ['eq', $params['changeId']]
        ], [
            'correct_file' => json_encode($correctFile)
        ]);
        $status = OrderCorrectRecordModel::getInstance()->value([
            'id' => ['eq', $params['changeId']]
        ], 'status');

        //
        $orderInfo = OrderCorrectRecordModel::getInstance()->find([
            'id' => ['eq', $params['changeId']]
        ], 'num_id, s_time');
        $oInfo = OrderModel::getInstance()->find($orderInfo['num_id'], 'product_id');
        $sTime = ClientProductService::getInstance()->getProductTimeRule([
            'product_id' => $oInfo['product_id'],
            'identification' => 2
        ]);
        $order['s_time'] = $sTime['startTime'] > $orderInfo['s_time'] ? $sTime['startTime'].' 00:00:00' : $orderInfo['s_time'];
        OrderEmployeeRecordModel::getInstance()->update([
            'change_id' => ['eq', $params['changeId']]
        ], [
            's_time' => $order['s_time']
        ]);
        $changeRecordIds = OrderEmployeeRecordModel::getInstance()->column([
            'id' => ['eq', $params['changeId']]
        ], 'record_id');
        OrderEmployeeRecordModel::getInstance()->update([
            'id' => ['in', $changeRecordIds]
        ], [
            'e_time' => datetime(strtotime($order['s_time']) - 24 * 3600, 'Y-m-d 23:59:59')
        ]);
        //

        return [
            'toTarget' => OrderCorrectRecordModel::getInstance()->value([
                'id' => ['eq', $params['changeId']]
            ], 'policy_money') > 0 && $status == 11 ? 'toPay' : 'toList'
        ];
    }

    /**
     * 批单支付
     */
    public function correctionPay($params)
    {
        $Validate = new \think\Validate([
            'payType' => 'require',
            'changeId' => 'require',
            'payName' => 'require',
            'payVoucher' => 'require|array',
        ], [
            'payType' => '支付方式无效',
            'changeId' => '批单标识无效',
            'payName' => '付款人必填',
            'payVoucher' => '付款凭证必填',
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $orderInfo = OrderCorrectRecordModel::getInstance()->find([
            'id' => ['eq', $params['changeId']]
        ], 'policy_money,num_id,s_time');

        $oInfo = OrderModel::getInstance()->find($orderInfo['num_id'], 'product_id');
        $sTime = ClientProductService::getInstance()->getProductTimeRule([
            'product_id' => $oInfo['product_id'],
            'identification' => 2
        ]);
        $order['s_time'] = $sTime['startTime'] > $orderInfo['s_time'] ? $sTime['startTime'].' 00:00:00' : $orderInfo['s_time'];
        OrderEmployeeRecordModel::getInstance()->update([
            'change_id' => ['eq', $params['changeId']]
        ], [
            's_time' => $order['s_time']
        ]);
        $changeRecordIds = OrderEmployeeRecordModel::getInstance()->column([
            'id' => ['eq', $params['changeId']]
        ], 'record_id');
        OrderEmployeeRecordModel::getInstance()->update([
            'id' => ['in', $changeRecordIds]
        ], [
            'e_time' => datetime(strtotime($order['s_time']) - 24 * 3600, 'Y-m-d 23:59:59')
        ]);

        $order['pay_money'] = $orderInfo['policy_money'];
        $order['pay_type'] = $params['payType'];
        $order['status'] = 2;//根据流程设定状态值
        if ($params['payType'] == 2)
        {
            $order['pay_voucher'] = json_encode([
                'payName' => $params['payName'],
                'payVoucher' => $params['payVoucher'],
                'payTime' => $this->stampToDateTime(time()),
                'payCardCode' => isset($params['payCardCode']) ? $params['payCardCode'] : ''
            ]);
            return OrderCorrectRecordModel::getInstance()->update([
                'id' => ['eq', $params['changeId']]
            ], $order);
        }else{
            $this->error('线上支付待对接');
        }
    }

    /**
     * 获取批单人员列表
     */
    public function getCorrectionPerson($params)
    {
        $Validate = new \think\Validate([
            'changeId' => 'require'
        ], [
            'changeId' => '批单标识无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $addPerson = OrderEmployeeRecordModel::getInstance()->select([
            'change_id' => ['eq', $params['changeId']]
        ], 'record_id,name,code,money,s_time,e_time,work_cate_title,work_type_title');
        $delPerson = OrderEmployeeRecordModel::getInstance()->select([
            'id' => ['in', array_column($addPerson, 'record_id')]
        ], 'name,code,money,s_time,e_time,work_cate_title,work_type_title');
        return [
            'addPerson' => $addPerson,
            'delPerson' => $delPerson
        ];
    }

    /**
     * 批改审核
     */
    public function correctionCheck($params)
    {
        $Validate = new \think\Validate([
            'changeId' => 'require',
            'type' => 'require',
        ], [
            'changeId' => '批单标识无效',
            'type' => '审核状态无效', //通过 1   驳回 2
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        Db::startTrans();
        try{
            switch ($params['type'])
            {
                case 1:

                    //修改保单状态  根据流程 识别下一步状态    打包投保资料 发送到保司
                    $changeInfo = OrderCorrectRecordModel::getInstance()->find([
                        'id' => ['eq', $params['changeId']]
                    ], 'num_id,add_num,change_num,s_time,e_time,correct_file');
                    $orderInfo = OrderModel::getInstance()->find($changeInfo['num_id'], 'insure_file,product_id,buy_count,s_time,e_time,is_have_bill');
                    $companyId = ProductModel::getInstance()->productValue($orderInfo['product_id'], 'company');
                    $toEmail = CompanyModel::getInstance()->find($companyId, 'insure_email,insure_email_spare');
                    $toEmail = array_values($toEmail);

                    //邮件标题： **方案 十级*% 新单 投保N人 保障期限 N - N  专票、普票、不开票
                    $emailTitle = '';
                    $proInfo = ProductModel::getInstance()->find($orderInfo['product_id'], 'product_name');
                    $emailTitle .= $proInfo['product_name'] . ' 批改 新增'.$changeInfo['add_num'].'人 减少'.$changeInfo['change_num'].'人 保障期限'.$changeInfo['s_time'].'至'.$orderInfo['e_time'];
                    $invoiceTitle = ' 不开票';
                    if ($orderInfo['is_have_bill'])
                    {
                        $invoiceType = OrderInvoiceModel::getInstance()->value($params['numId'], 'type');
                        $invoiceTitle = $invoiceType == 2 ? ' 专票' : ' 普票';
                    }
                    $emailTitle .= $invoiceTitle;
                    if (!empty($changeInfo['correct_file']))
                    {
                        $emailData = [
                            'toEmail' => implode(',', $toEmail),
                            'title' => $emailTitle,
                            'isZip' => true,
                            'files' => json_decode($changeInfo['correct_file'], true)
                        ];
                        EmsService::getInstance()->sendEmail($emailData);
                    }
                    OrderEmployeeRecordModel::getInstance()->update([
                        'change_id' => ['eq', $params['changeId']]
                    ], [
                        'status' => 1
                    ]);
                    OrderEmployeeRecordModel::getInstance()->update([
                        'id' => ['in', OrderEmployeeRecordModel::getInstance()->column([
                            'change_id' => ['eq', $params['changeId']]
                        ], 'record_id')]
                    ], [
                        'status' => 1,
                        'e_time' => datetime(strtotime(OrderEmployeeRecordModel::getInstance()->value([
                                'change_id' => ['eq', $params['changeId']]
                            ], 's_time')) - 24 * 3600, 'Y-m-d 23:59:59')
                    ]);
                    $res = OrderCorrectRecordModel::getInstance()->update([
                        'id' => ['eq', $params['changeId']]
                    ], [
                        'status' => 3
                    ]);

                    break;
                case 2:
                    OrderCorrectRecordModel::getInstance()->update([
                        'id' => ['eq', $params['changeId']]
                    ], [
                        'status' => 4
                    ]);
                    $res = OrderEmployeeRecordModel::getInstance()->update([
                        'change_id' => ['eq', $params['changeId']]
                    ], [
                        'status' => 0
                    ]);
                    break;
            }
            LogService::getInstance()->writeSysLog([
                'operation' => '/api/order/correctionCheck',
                'title' => '批单审核：批单ID'.$params['changeId'].($params['type'] == 2 ? '驳回' : '通过'). '  '.(isset($params['desc']) ? $params['desc'] : ''),
                'content' => [
                    'changeId' => 'changeId'.$params['changeId'],
                    'params' => $params
                ],
            ]);
            Db::commit();
            return $res;
        }catch (Exception $e)
        {
            Db::rollback();
            $this->error($e->getMessage());
        }
    }

    /**
     * 上传保单、保单号、发票
     */
    public function uploadPolicyFileInfo($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require',
        ], [
            'numId' => '订单流水号无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $isHaveBill = OrderModel::getInstance()->value($params['numId'], 'is_have_bill');
        if (!$isHaveBill)
        {
            $params['billFile'] = ' ';
        }

        $saveData = [];
        if (!empty($params['policyFile']))
        {
            $saveData['policy_file'] = $params['policyFile'];
        }
        if (!empty($params['policyNum']))
        {
            $saveData['policy_num'] = $params['policyNum'];
        }
        if (!empty($params['billFile']))
        {
            $saveData['bill_file'] = $params['billFile'];
        }
        LogService::getInstance()->writeSysLog([
            'operation' => '/api/order/uploadPolicyFileInfo',
            'title' => '更新保单&发票信息，流水号'.$params['numId'],
            'content' => [
                'numId' => 'numId'.$params['numId'],
                'params' => $params
            ],
        ]);
        return empty($saveData) ? false : OrderModel::getInstance()->update($params['numId'], $saveData);
    }

    /**
     * 上传批单、批单号、发票
     */
    public function uploadCorrectionFileInfo($params)
    {
        $Validate = new \think\Validate([
            'changeId' => 'require',
        ], [
            'changeId' => '批单标识无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $numId = OrderCorrectRecordModel::getInstance()->value([
            'id' => ['eq', $params['changeId']]
        ], 'num_id');
        $isHaveBill = OrderModel::getInstance()->value($numId, 'is_have_bill');
        if (!$isHaveBill)
        {
            $params['billFile'] = ' ';
        }
        $saveData = [];
        if (!empty($params['policyFile']))
        {
            $saveData['policy_file'] = $params['policyFile'];
        }
        if (!empty($params['correctNum']))
        {
            $saveData['correct_num'] = $params['correctNum'];
        }
        if (!empty($params['billFile']))
        {
            $saveData['bill_file'] = $params['billFile'];
        }
        LogService::getInstance()->writeSysLog([
            'operation' => '/api/order/uploadCorrectionFileInfo',
            'title' => '更新批单&发票信息，批改ID'.$params['changeId'],
            'content' => [
                'changeId' => 'changeId'.$params['changeId'],
                'params' => $params
            ],
        ]);
        return empty($saveData) ? false : OrderCorrectRecordModel::getInstance()->update([
            'id' => ['eq', $params['changeId']]
        ], $saveData);
    }

    /**
     * 检测是否拒保
     */
    public function checkInsuredStatus($params)
    {
        $Validate = new \think\Validate([
            'companyName' => 'require',
            'companyCode' => 'require',
            'province' => 'require',
            'city' => 'require',
            'area' => 'require',
            'productId' => 'require',
        ], [
            'companyName' => '投保人名称无效',
            'companyCode' => '投保人证件号无效',
            'province' => '投保地址无效',
            'city' => '投保地址无效',
            'area' => '投保地址无效',
            'productId' => '产品标识无效',
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $companyBackList = BackListCompanyModel::getInstance()->find([
            'code' => ['eq', $params['companyCode']],
            'product_id' => ['like',  '%'.$params['productId'].'%']
        ]);
        $msg = '';
        if (!empty($companyBackList))
        {
            $msg .= '该公司信息不可投保当前方案';
        }
        $keywordsList = BackListKeywordsModel::getInstance()->column([
            'product_id' => ['eq', $params['productId']]
        ]);
        if (!empty($keywordsList))
        {
            foreach ($keywordsList as $k => $v)
            {
                if (!empty($v))
                {
                    if (strpos($params['companyName'], $v) !== false)
                    {
                        $msg .= '该公司信息涉及敏感词';
                    }
                }
            }
        }
        $areaBackList = BackListAreaModel::getInstance()->select([
            'product_id' => ['eq', $params['productId']]
        ]);
        $areaBackList = explode(',', implode(',', array_merge(array_column($areaBackList, 'province'), array_column($areaBackList, 'city'), array_column($areaBackList, 'area'))));
        if (in_array($params['province'], $areaBackList) || in_array($params['city'], $areaBackList) || in_array($params['area'], $areaBackList))
        {
            $msg .= '当前地区不可投保';
        }
        if (!empty($msg))
        {
            $this->error($msg);
        }
        return true;
    }

    /**
     * 获取是否固定投保人
     */
    public function getPolicyHolder($params)
    {
        $Validate = new \think\Validate([
            'productId' => 'require',
        ], [
            'productId' => '产品标识无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        $rule = ProductRuleModel::getInstance()->find($params['productId']);
        $baseRule = json_decode($rule['base_rule'], true);
        return [
            'isAppointAapplication' => !empty($baseRule['isAppointAapplication']) ? $baseRule['isAppointAapplication'] : '',
            'applicationName' => !empty($baseRule['applicationName']) ? $baseRule['applicationName'] : '',
            'applicationCode' => !empty($baseRule['applicationCode']) ? $baseRule['applicationCode'] : '',
            'applicationLegalPerson' => !empty($baseRule['applicationLegalPerson']) ? $baseRule['applicationLegalPerson'] : '',
            'applicationPhone' => !empty($baseRule['applicationPhone']) ? $baseRule['applicationPhone'] : '',
            'applicationAddress' => !empty($baseRule['applicationAddress']) ? $baseRule['applicationAddress'] : '',
            'applicationCodeImg' => !empty($baseRule['applicationCodeImg']) ? $baseRule['applicationCodeImg'] : '',
            'applicationProvince' => !empty($baseRule['applicationProvince']) ? $baseRule['applicationProvince'] : '',
            'applicationCity' => !empty($baseRule['applicationCity']) ? $baseRule['applicationCity'] : '',
            'applicationArea' => !empty($baseRule['applicationArea']) ? $baseRule['applicationArea'] : '',
            'applicationProvinceName' => !empty($baseRule['applicationProvince']) ? CommonService::getInstance()->getAreaName($baseRule['applicationProvince']) : '',
            'applicationCityName' => !empty($baseRule['applicationCity']) ? CommonService::getInstance()->getAreaName($baseRule['applicationCity']) : '',
            'applicationAreaName' => !empty($baseRule['applicationArea']) ? CommonService::getInstance()->getAreaName($baseRule['applicationArea']) : '',
        ];
    }

    /**
     * 取消订单接口
     */
    public function cancelOrder($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require',
        ], [
            'numId' => '订单流水号标识无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        OrderModel::getInstance()->update($params['numId'], [
            'status' => 8
        ]);
        return OrderEmployeeRecordModel::getInstance()->update([
            'num_id' => ['eq', $params['numId']]
        ], [
            'status' => 0
        ]);
    }

    /**
     * 取消批单接口
     */
    public function cancelCorrection($params)
    {
        $Validate = new \think\Validate([
            'changeId' => 'require',
        ], [
            'changeId' => '批改标识无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }
        OrderCorrectRecordModel::getInstance()->update([
            'id' => ['eq', $params['changeId']]
        ], [
            'status' => 8
        ]);
        return OrderEmployeeRecordModel::getInstance()->update([
            'change_id' => ['eq', $params['changeId']]
        ], [
            'status' => 0
        ]);
    }

    /**
     * 获取开户行信息
     */
    public function getPaymentInfo($params)
    {
        $Validate = new \think\Validate([
            'numId' => 'require'
        ], [
            'numId' => '订单流水号标识无效'
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }

    }

    /**
     * 获取操作日志
     */
    public function getOperationLog()
    {
        $numId = $this->request->param('numId', '');
        $changeId = $this->request->param('changeId', '');
        if (!empty($numId))
        {
            $where = [
                'content' => ['like', '%numId'.$numId.'%']
            ];
        }
        if (!empty($changeId))
        {
            $where = [
                'content' => ['like', '%changeId'.$changeId.'%']
            ];
        }
        $logList = [];
        if (!empty($where))
        {
            $logList = Db::name('admin_log')->where($where)->field('username,title,createtime')->select();
            foreach ($logList as $k => &$v)
            {
                $v['createtime'] = $this->stampToDateTime($v['createtime']);
            }
        }
        return $logList;
    }

    /**
     * 获取常用投保人列表
     */
    public function getApplicationList($params)
    {
        $list = OrderApplicationModel::getInstance()->select([
            'admin_id' => ['eq', $this->uid],
        ], 'id, name, code, province, city, area, address, phone, code_img, legal_person, business_site', 'code');
        foreach ($list as $k => &$v)
        {
            $v['provinceName'] = CommonService::getInstance()->getAreaName($v['province']);
            $v['cityName'] = CommonService::getInstance()->getAreaName($v['city']);
            $v['areaName'] = CommonService::getInstance()->getAreaName($v['area']);
        }
        return $list;
    }

    /**
     * 获取常用被保人
     */
    public function getInsuredList($params)
    {
        $list = OrderInsuredModel::getInstance()->select([
            'admin_id' => ['eq', $this->uid],
        ], 'id, name, code, province, city, area, address, phone, code_img, legal_person, business_site', 'code');
        foreach ($list as $k => &$v)
        {
            $v['provinceName'] = CommonService::getInstance()->getAreaName($v['province']);
            $v['cityName'] = CommonService::getInstance()->getAreaName($v['city']);
            $v['areaName'] = CommonService::getInstance()->getAreaName($v['area']);
        }
        return $list;
    }

    /**
     * 校验产品投保规则
     */
    public function checkProductRule($personList, $plan, $type = 'insure')
    {
        if ($type == 'insure')
        {
            if (count($personList) < $plan['insureNum'])
            {
                $this->error('该方案投保人数不能低于'.$plan['insureNum'].'人');
            }
            $man = 0;$woman = 0;$msg = '';
            if (!isset($plan['insureAge']['ageRange']))
            {
                $plan['insureAge']['ageRange'] = [
                    [
                        'startAge' => $plan['insureAge']['startAge'],
                        'endAge' => $plan['insureAge']['endAge'],
                        'sex' => 0,
                        'ageRange' => 100
                    ]
                ];
            }
            foreach ($plan['insureAge']['ageRange'] as $key => $val)
            {
                $age[$val['startAge'].'-'.$val['endAge']] = 0;
                foreach ($personList as $k => $v)
                {
                    $tAge = IdentityService::getInstance()->getAge($v['idCardNum']);
                    $tSex = IdentityService::getInstance()->getSex($v['idCardNum']);
                    $tSex == 2 ? $woman++ : $man++;
                    if ($tAge < $plan['insureAge']['startAge'] || $tAge > $plan['insureAge']['endAge'])
                    {
                        $msg .= $v['name'].' 超出可投保年龄('.$plan['insureAge']['startAge'].'-'.$plan['insureAge']['endAge'].')范围 ';
                    }
                    if ($tSex == $val['sex'] || empty($val['sex']))
                    {
                        if ($tAge >= $val['startAge'] && $tAge <= $val['endAge'])
                        {
                            $age[$val['startAge'].'-'.$val['endAge']]++;
                        }
                    }
                }
                if (( $age[$val['startAge'].'-'.$val['endAge']] / count($personList) * 100 ) > $val['ageRange'])
                {
                    $msgTxt = empty($val['sex']) ? '的人数' : ($val['sex'] == 2 ? '的女性人数' : '的男性人数');
                    $msg .= '年龄在'.$val['startAge'].'-'.$val['endAge'].'之间'.$msgTxt.'不能超过总人数占比'.$val['ageRange'].'% ';
                }
            }

            if (!empty($msg))
            {
                $this->error($msg);
            }
        }
        return true;
    }

}